package com.ec.rs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ec.api.client.ElderProfileClient;
import com.ec.api.client.UserClient;
import com.ec.common.domain.PageVO;
import com.ec.common.domain.Result;
import com.ec.common.exception.CommonException;
import com.ec.rs.domain.dto.CheckInOutRequestDTO;
import com.ec.rs.domain.dto.ReviewRequestDTO;
import com.ec.rs.domain.po.Bed;
import com.ec.rs.domain.po.CheckInOutRequest;
import com.ec.rs.enums.BedStatus;
import com.ec.rs.enums.RequestStatus;
import com.ec.rs.enums.RequestType;
import com.ec.rs.mapper.BedMapper;
import com.ec.rs.mapper.CheckInOutRequestMapper;
import com.ec.rs.service.ResidenceService;
import com.ec.rs.util.CheckInOutService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

@Slf4j
@Service
@RequiredArgsConstructor
public class ResidenceServiceImpl implements ResidenceService {
    private final CheckInOutRequestMapper requestMapper;
    private final BedMapper bedMapper;
    private final ElderProfileClient elderProfileClient;
    private final UserClient userClient;
    private final CheckInOutService checkInOutService;

    @Override
    public Result<Void> submitRequest(CheckInOutRequestDTO dto) {
        if (dto.getRequestType() != RequestType.CHECK_IN && dto.getRequestType() != RequestType.CHECK_OUT) {
            return Result.error("错误的请求类型");
        }
        // 判断用户是否存在
        Result<Boolean> userResult = userClient.checkUserExists(dto.getElderlyUserId());
        if (!userResult.getData()) {
            return Result.error("用户不存在");
        }
        CheckInOutRequest request = CheckInOutRequest.builder()
                .elderlyUserId(dto.getElderlyUserId())
                .requestType(dto.getRequestType())
                .status(RequestStatus.PENDING)
                .createdAt(LocalDateTime.now())
                .build();
        requestMapper.insert(request);
        return Result.ok();
    }

    @Override
    @Transactional
    public Result<Void> reviewRequest(Long id, ReviewRequestDTO dto) {
        CheckInOutRequest request = requestMapper.selectById(id);
        if (request == null) {
            return Result.error("错误的请求ID");
        }
        if (dto.getStatus() != RequestStatus.APPROVED && dto.getStatus() != RequestStatus.REJECTED) {
            return Result.error("错误的审核状态");
        }

        request.setStatus(dto.getStatus());
        request.setApprovedByAdminId(dto.getApprovedByAdminId());
        request.setNotes(dto.getNotes());
        requestMapper.updateById(request);

        if (dto.getStatus() == RequestStatus.APPROVED) {
            if (request.getRequestType() == RequestType.CHECK_IN) {
                // 分配床位
                if (dto.getBedId() == null) {
                    return Result.error("床位ID不能为空");
                }
                Bed bed = bedMapper.selectById(dto.getBedId());
                if (bed == null || bed.getStatus() != BedStatus.VACANT) {
                    return Result.error("床位不存在或已被占用");
                }
                bed.setStatus(BedStatus.OCCUPIED);
                bed.setOccupiedByUserId(request.getElderlyUserId());
                bedMapper.updateById(bed);

                // 调用 profile-service 更新床位ID
                Result<Boolean> bedResult = elderProfileClient.updateBedId(request.getElderlyUserId(), Long.valueOf(dto.getBedId()));
                if (!bedResult.getData()) {
                    throw new RuntimeException("更新老人床位ID失败: " + bedResult.getMsg());
                }

                // 调用 profile-service 更新入住状态
                Result<Void> statusResult = elderProfileClient.updateElderlyStatusByUserId(request.getElderlyUserId(), "在住");
                if (!statusResult.success()) {
                    throw new RuntimeException("更新老人入住状态失败: " + statusResult.getMsg());
                }
            } else if (request.getRequestType() == RequestType.CHECK_OUT) {
                // TODO：需要判断其是否已经缴费
                if(!checkInOutService.handleCheckOutRequest(dto, request.getElderlyUserId(), request.getCreatedAt())){
                    return Result.error("订单生成失败");
                }
                // 释放床位
                QueryWrapper<Bed> bedQuery = new QueryWrapper<>();
                bedQuery.eq("occupied_by_user_id", request.getElderlyUserId());
                Bed bed = bedMapper.selectOne(bedQuery);
                if (bed != null) {
                    bed.setStatus(BedStatus.VACANT);
                    bed.setOccupiedByUserId(null);
                    bedMapper.updateById(bed);

                    // 调用 profile-service 更新床位ID为 null
                    Result<Boolean> bedResult = elderProfileClient.updateBedId(request.getElderlyUserId(), (long) -1);
                    if (!bedResult.getData()) {
                        throw new RuntimeException("更新老人床位ID失败: " + bedResult.getMsg());
                    }
                }

                // 调用 profile-service 更新入住状态
                Result<Void> statusResult = elderProfileClient.updateElderlyStatusByUserId(request.getElderlyUserId(), "退住");
                if (!statusResult.success()) {
                    throw new RuntimeException("更新老人入住状态失败: " + statusResult.getMsg());
                }
            }
        }
        return Result.ok();
    }

    @Override
    public Result<PageVO<CheckInOutRequest>> listRequests(int page, int size, String requestType, String status) {
        Page<CheckInOutRequest> pageObj = new Page<>(page, size);
        QueryWrapper<CheckInOutRequest> wrapper = new QueryWrapper<>();
        if (requestType != null) {
            RequestType reqType = RequestType.of(requestType);
            wrapper.eq("request_type", reqType.getValue());
        }
        if (status != null) {
            RequestStatus reqStatus = RequestStatus.of(status);
            wrapper.eq("status", reqStatus.getValue());
        }
        Page<CheckInOutRequest> resultPage = requestMapper.selectPage(pageObj, wrapper);
        return Result.ok(PageVO.of(resultPage));
    }
}